// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "PacketHandle.h"
#include "Log/logging.h"
#include "HWSecure/include/securec.h"

/**
 * @功能描述：PacketHandle构造函数
 * @参数 [in] type：数据包类型
 * @参数 [in] hook：钩子函数
 * @参数 [in] isSingleFragment：是否单包（不分片）
 */
PacketHandle::PacketHandle(VMIMsgType type, RENDER_SERVER_HANDLE_HOOK hook, bool isSingleFragment)
    : m_msgReassemble(type), m_type(type), m_hook(hook)
{
    m_msgReassemble.SetSingleSend(isSingleFragment);
}

/**
 * @功能描述：PacketHandle析构函数
 */
PacketHandle::~PacketHandle()
{
    INFO("~PacketHandle");
    m_msgReassemble.Clear();
}

/**
 * @功能描述：包处理函数，将包存储到队列中
 * @参数 [in] packet：包的指针
 */
void PacketHandle::Handle(const VmiBuffer& packet)
{
    uint8_t *pktData = packet.GetPointer();
    size_t pktSize = packet.GetSize();
    if (pktData == nullptr || pktSize == 0 || pktSize < sizeof(StreamMsgHead)) {
        ERR("bad packet, data:%p, size:%zu", pktData, pktSize);
        VmiFreeBuffer(pktData);
        return;
    }

    StreamMsgHead *msg = reinterpret_cast<StreamMsgHead *>(packet.GetPointer());
    std::pair<uint8_t *, uint32_t> packetPair = m_msgReassemble.Reassemble(*msg);
    uint8_t *reassemblePacket = packetPair.first;
    uint32_t dataLen = packetPair.second;
    if (reassemblePacket == nullptr || dataLen == 0) {
        return;
    }

    if (m_hook == nullptr) {
        ERR("error: not found hook to handle packet(type:%u), free it", m_type);
        VmiFreeBuffer(reassemblePacket);
        return;
    }

    uint32_t ret = m_hook(reassemblePacket, dataLen);
    if (ret != 0) {
        ERR("call hook error, ret:%u", ret);
    }
}

/**
 * @功能描述：清空包队列
 */
void PacketHandle::ClearQueue()
{
    m_msgReassemble.Clear();
}
